const deepEqual = (obj1, obj2) => {
	// 处理原始值或同一引用
	if (obj1 === obj2) {
		return true;
	}
	// 处理 null 或非对象类型
	if (obj1 === null || obj2 === null || typeof obj1 !== 'object' || typeof obj2 !== 'object') {
		return false;
	}
	
	// 检查是否都是数组
	const bothAreArrays = Array.isArray(obj1) && Array.isArray(obj2);
	if (bothAreArrays) {
		// 数组长度不同则不相等
		if (obj1.length !== obj2.length) {
			return false;
		}
		// 使用 Map 统计每个元素的出现次数
		const countMap1 = countElements(obj1);
		const countMap2 = countElements(obj2);
		// 比较两个 Map 是否相同
		if (countMap1.size !== countMap2.size) {
			return false;
		}
		for (const [key, value] of countMap1) {
			if (!countMap2.has(key) || countMap2.get(key) !== value) {
				return false;
			}
		}
		return true;
	}
	
	// 处理普通对象
	const keys1 = Object.keys(obj1);
	const keys2 = Object.keys(obj2);
	if (keys1.length !== keys2.length) {
		return false;
	}
	for (const key of keys1) {
		if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {
			return false;
		}
	}
	return true;
}

// 辅助函数：统计数组中每个元素的出现次数
const countElements = (arr) => {
	const map = new Map();
	for (const item of arr) {
		// 使用 JSON.stringify 作为键（简化处理，不考虑函数等特殊情况）
		const key = typeof item === 'object' && item !== null ? JSON.stringify(item) : item;
		map.set(key, (map.get(key) || 0) + 1);
	}
	return map;
}

/**
 * 比较是否一致
 * obj1：新对象
 * obj2：旧对象，参考标准
 */
module.exports = {
	bool(obj1, obj2) { // 比较是否相同
		return deepEqual(obj1, obj2);
	},
	differ(obj1, obj2) { // 返回差异性的地方
		if (deepEqual(obj1, obj2)) { // 一致就返回undefined
			return undefined;
		}
		/**
		 * 不一致的情况
		 * 数组就直接返回
		 * 对象只比较第一层内容，如果一致就不要该key
		 * 其它类型直接返回
		 */
		if (Object.prototype.toString.call(obj1) === '[object Object]') { // 对象只比较第一层内容
			if (Object.prototype.toString.call(obj2) === '[object Object]') {
				let result = {};
				for (let key in obj1) {
					if (!deepEqual(obj1[key], obj2[key])) {
						if (typeof obj1[key] === 'object') {
							result[key] = JSON.parse(JSON.stringify(obj1[key]));
						} else {
							result[key] = obj1[key];
						}
					}
				}
				return result;
			}
		}
		// 数组以及其他类型都直接返回
		return obj1;
	}
}